/**
 * 	Examples:
 * 
 *	UniQLFullText obj = new UniQLFullText()
 *	.addField("telephone.FULLTEXT_ALL")
 *	.setParams(new ArrayList(Arrays.asList("JDYT M200".split(" "))))
 * 	
 */
package cz.acies.uniql.sql.element;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.dom.DOMElement;


import cz.acies.uniql.dialect.Dialect;
import cz.acies.uniql.dialect.MSSQLDialect;
import cz.acies.uniql.dialect.MySQLDialect;
import cz.acies.uniql.dialect.OracleDialect;
import cz.acies.uniql.sql.UniQLExpr;

public class UniQLFullText extends UniQLExpr
{
	private static final long serialVersionUID = -8239650331420951861L;

	public static void main(String[] args) {
		Dialect dialect = null;
		try {
			//dialect = new MySQLDialect();
			dialect = new MSSQLDialect();
			//dialect = new OracleDialect();
			UniQLFullText obj = new UniQLFullText()
			//.addField("telephone.FULLTEXT_ALL")
			.addField("telephone.NAME")
			.setParams(new ArrayList<String>(Arrays.asList("jdyt m200".split(" "))))
			;
			obj.setDialect(dialect);
			System.out.println(""+obj.translate());
			
		} catch (Exception exc) {
			exc.printStackTrace();
		}
	}

	private ArrayList<String> params = new ArrayList<String>();
	private List<UniQLExpr> fields = new ArrayList<UniQLExpr>();
	
	public UniQLFullText() {
		super();
	}

	public UniQLFullText(Dialect dialect) {
		super(dialect);
	}
	// -----  -----------------------------------------------------------------

	public UniQLFullText addField(String field) {
		this.fields.add(new UniQLColumn(field));
		return this;
	}
	
	public UniQLFullText addField(UniQLExpr field) {
		this.fields.add(field); 
		return this;
	}
	
	// -----  -----------------------------------------------------------------
	
	public UniQLFullText addParam(String param) {
		this.getParams().add(param);
		return this;
	}

	public UniQLFullText addKey(String param) {
		this.getParams().add(param);
		return this;
	}
	
	//
	public ArrayList<String> getParams() {
		if (params == null) new ArrayList<String>();
		return params;
	}
 
	public ArrayList<String> getKeys() {
		return getParams();
	}

	//
	public UniQLFullText setParams(ArrayList<String> params) {
		this.params = params;
		return this;
	}
	
	public UniQLFullText setKeys(ArrayList<String> params) {
		return this.setParams(params);
	}

	// -----  ------------------  ---------------------------------------------	
	
	/* (non-Javadoc)
	 * @see cz.acies.uniql.sql.UniQLExpr#translate()
	 */
	public String translate() throws Exception {
		StringBuffer sb = new StringBuffer();
		if (getDialect() instanceof MySQLDialect) {
			try {
				sb.append("MATCH(");
				if (fields != null) {
					for (Iterator<UniQLExpr> iterator = fields.iterator(); iterator.hasNext();) {
						UniQLExpr field = iterator.next();
						field.setUniQLProperties(this);
						sb.append(field.translate());
						if (iterator.hasNext()) sb.append(", ");
					}
				}
				sb.append(") AGAINST ('");
				int count = params.size();
				for (int i = 0; i < count; i++) {
					String value = (String)params.get(i);
					//value = StringUtils.win2asc(value);
					//value = this.getDialect().encodeFullText(value);
					if (i > 0) sb.append(" ");
					sb.append(""+value);
				}
				sb.append("' IN BOOLEAN MODE)");				
			} catch (Exception exc) {
				exc.printStackTrace();
			}
		} else if (getDialect() instanceof MSSQLDialect) {
			//CONTAINS(FULLTEXT_ALL, '"cz*" AND "mx*"')
			System.out.println("UniQLFullText.translate().params = "+params);
			int count = params.size();
			if (fields != null && !fields.isEmpty()  && count > 0) {
				sb.append("CONTAINS(");
				for (Iterator<UniQLExpr> iterator = fields.iterator(); iterator.hasNext();) {
					UniQLExpr field = iterator.next();
					field.setUniQLProperties(this);
					sb.append(field.translate()+", '");
				}
				for (int i = 0; i < count; i++) {
					String key = (String)params.get(i);
					sb.append("\""+key+"*\"");
					if (i < (count-1)) sb.append(" AND ");
				}
				sb.append("')");
			}
		} else if (getDialect() instanceof OracleDialect) {			
			int count = params.size();
			if (fields != null && !fields.isEmpty() && count > 0) {
				UniQLExpr field = fields.get(0);
				field.setUniQLProperties(this);
				for (int i = 0; i < count; i++) {
					String key = (String)params.get(i);
					sb.append("CTXSYS.CONTAINS("+field+", "+key+"%, "+i+")");
					if (i < (count-1)) sb.append(" AND ");
				} 
			}
		}
		return sb.toString();
	}

	// -----  -----------------------------------------------------------------
	
	/* (non-Javadoc)
	 * @see cz.acies.uniql.sql.UniQLExpr#transToXML()
	 */
	public String transToXML() throws Exception {
		DOMElement node = new DOMElement("UniQLFullText");
		transToXML(node);
		return node.asXML();
	}
	
	/* (non-Javadoc)
	 * @see cz.acies.uniql.sql.UniQLExpr#transToXML(org.dom4j.dom.DOMElement)
	 */
	public DOMElement transToXML(DOMElement node) throws Exception {
		node.setName("UniQLFullText");
		if (fields != null) {
			DOMElement root = new DOMElement("fields");
			node.add(root);
			for (Iterator<UniQLExpr> iterator = fields.iterator(); iterator.hasNext();) {
				UniQLExpr field = (UniQLExpr) iterator.next();
				String xml = field.transToXML();
				Document doc = DocumentHelper.parseText(xml);
				Element element = doc.getRootElement();
				root.add(element); 				
			}
		}
		if (params != null) {
			DOMElement root = new DOMElement("keys");
			for (Iterator<String> iterator = params.iterator(); iterator.hasNext();) {
				String s = iterator.next();
				DOMElement keynode = new DOMElement("key");
				keynode.setAttribute("value", ""+s);
				root.add(keynode);
			}
			node.add(root);
		}
		return node;
	}

	/* (non-Javadoc)
	 * @see cz.acies.uniql.sql.UniQLExpr#xmlToExpr(java.lang.String)
	 */
	public UniQLExpr xmlToExpr(String xml) throws Exception {
		Document doc = DocumentHelper.parseText(xml);
		return xmlToExpr(doc.getRootElement());
	}

	/* (non-Javadoc)
	 * @see cz.acies.uniql.sql.UniQLExpr#xmlToExpr(org.dom4j.Element)
	 */
	@SuppressWarnings("unchecked")
	public UniQLExpr xmlToExpr(Element node) throws Exception {
		ArrayList nodelist = new ArrayList(node.elements());
		for (int i = 0; i < nodelist.size(); i++) {
			Element element = (Element)nodelist.get(i);
			String nodename = element.getName();
			UniQLExpr expr = null; 
			if (nodename.equals("fields")) {
				ArrayList fieldist = new ArrayList(element.elements());
				for (int j = 0; j < fieldist.size(); j++) {
					Element fieldnode = (Element)fieldist.get(j);
					String name = fieldnode.getName();
					if (name.equals("UniQLColumn")) {
						expr = new UniQLColumn(getDialect()).xmlToExpr(fieldnode);
						if (expr != null) { this.addField(expr); }
					}
				}
			}
			if (nodename.equals("keys")) {
				ArrayList keyist = new ArrayList(element.elements()); 
				for (int j = 0; j < keyist.size(); j++) {
					Element keynode = (Element)keyist.get(j);
					String name = keynode.getName();
					if (name.equals("key")) {
						String value = keynode.attributeValue("value");
						if (value != null) {
							params.add(value);
						}
					}
				}
			}
		}
		return this;
	}

	// -----  -----------------------------------------------------------------
	
	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	public String toString() {
		String s = "";
		s += "fields: "+this.fields+", params: "+this.params;
		return "" + this.getClass().getSimpleName() + "( " + s + " )";
	}

}
